﻿#include <tuple>
#include <type_traits>
#include <functional>
using namespace std;

#include "nggs/tuple_helper.h"
#include "nggs/print.h"
#include "nggs/util.h"

struct printer
{
    void operator()(int i)
    {
        nggs::Println("int=[", i, "]");
    }

    void operator()(double i)
    {
        nggs::Println("double=[", i, "]");
    }

    void operator()(char i)
    {
        nggs::Println("char=[", i, "]");
    }

    void operator()(const char *i)
    {
        nggs::Println("const char*=[", i, "]");
    }
};

struct adder
{
    void operator()(int &i)
    {
        i += 1;
    }

    void operator()(double &i)
    {
        i += 1;
    }

    void operator()(char &i)
    {
        i += 1;
    }
};

template <typename... Args>
auto add(Args &&...args)
{
    return (args + ...);
}

int main(int argc, char *argv[])
{
    nggs::Println("add result=", add(1, 2, 3, 4));

    printer p;

    {
        std::tuple<int, double, char> t = std::make_tuple(1, 2.3, '4');

        nggs::ConstEachInTuple(t, std::bind(p, std::placeholders::_1));

        nggs::EachInTuple(t, std::bind(adder(), std::placeholders::_1));

        nggs::ConstEachInTuple(t, std::bind(p, std::placeholders::_1));
    }
    {
        std::tuple<int, double, char, short, const char *> t = std::make_tuple(1, 2.3, 2, 1, nullptr);
        auto e = nggs::GetTupleElementByType<const char *>(t);
        nggs::Println(e);
    }
    {
        std::tuple<int, double, char, short, const char *> t = std::make_tuple(1, 2.3, 2, 1, "test");
        nggs::SetTupleElementByType<const char *>(t, "hello world");
        auto e = nggs::GetTupleElementByType<const char *>(t);
        nggs::Println(e);
    }

    int key = 1;
    if (nggs::AnyOne(key, 0, 2, 1, 1))
    {
        nggs::Println("AnyOne");
    }

    return 0;
}
